import { EventEmitter, WebSocket } from "ws";
import { MyServer } from "./MyServer";
import { ApiMsgEnum, IModel, binaryDecode, binaryEncode } from "../Common";
import { buffer2ArrayBuffer } from "../Utils/index"
export enum ConnectionEventType {
    close = 'close'
}

interface IItem {
    fun: Function
    ctx: unknown
}

export class Connection extends EventEmitter {

    public playerId: number = 0
    public msgMap: Map<ApiMsgEnum, IItem[]> = new Map()
    constructor(private server: MyServer, private socket: WebSocket,) {
        super()
        this.socket.on('close', (code: number, reason: Buffer) => {
            this.emit(ConnectionEventType.close)
        })

        this.socket.on('message', (buffer: Buffer) => {

            try {
                const json = binaryDecode(buffer2ArrayBuffer(buffer))
                const { name, data } = json

                if (this.server.apiMap.has(name)) {
                    try {
                        const cb = this.server.apiMap.get(name)
                        const res = cb?.call(null, this, data)
                        this.sendMsg(name, { success: true, res })
                    } catch (e) {
                        this.sendMsg(name, { success: false, error: (e as Error).message })
                    }
                } else {
                    try {
                        const map = this.msgMap.get(name)
                        if (map) {
                            for (const { fun, ctx } of map) {
                                fun.call(ctx, this, data)
                            }
                        }
                    } catch (error) {
                        console.log(error)
                    }
                }

            } catch (error) {
                console.log('数据不合法', error)
            }
        })
    }

    listening<T extends keyof IModel['msg']>(name: T, fun: Function, ctx: unknown) {
        const map = this.msgMap.get(name)
        if (map) {
            map.push({ ctx, fun })
        } else {
            this.msgMap.set(name, [{ ctx, fun }])
        }
    }

    unlistening<T extends keyof IModel['msg']>(name: T, fun: Function, ctx: unknown) {
        const map = this.msgMap.get(name)
        if (map) {
            const index = map.findIndex(v => v.fun === fun && v.ctx === ctx)
            index > -1 && map.splice(index, 1)
        }
    }

    sendMsg<T extends keyof IModel['msg']>(name: T, data: IModel['msg'][T]) {
        // console.log(name, JSON.stringify(data))
        const buffer = Buffer.from(binaryEncode(name, data).buffer)
        this.socket.send(buffer)
    }

}